package com.sam.nosql;

import android.test.InstrumentationTestCase;
import android.util.Log;

import com.colintmiller.simplenosql.DataComparator;
import com.colintmiller.simplenosql.DataFilter;
import com.colintmiller.simplenosql.NoSQL;
import com.colintmiller.simplenosql.NoSQLEntity;
import com.colintmiller.simplenosql.OperationObserver;
import com.colintmiller.simplenosql.RetrievalCallback;
import com.sam.data.DbDataUtil;
import com.sam.data.TimeUtils;
import com.sam.data.UserData;

import java.util.ArrayList;
import java.util.List;

/**
 * &lt;br&gt;Created
 *
 * @author wangds
 * @see
 */
public class SimpleNoSqlTest extends InstrumentationTestCase{
    public final static String TAG ="DBTEST_SimpleNoSql";
    private final static String BUCKET_ID ="bucket";
    private MainActivity mMainActivity;
    private NoSQL noSQL;
    private int finishCount = 0;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mMainActivity  = launchActivity("com.sam.nosql", MainActivity.class, null);
        noSQL = NoSQL.with(mMainActivity);
        noSQL.using(UserData.class)
                .bucketId(BUCKET_ID).addObserver(new OperationObserver() {
            @Override
            public void hasFinished() {
                finishCount++;
            }
        }).delete();
        waitForThread(1);
        finishCount = 0;
    }

    public void testCurd(){
//        Saving
        NoSQLEntity<UserData> entity = new NoSQLEntity<UserData>(BUCKET_ID, "entityId");
        final UserData data = new UserData();
        data.setName("Colin");
        data.setHeight(1.01f);
        data.setAge(12);
        entity.setData(data);
        noSQL.using(UserData.class).save(entity);

//        retrieve
        noSQL.using(UserData.class)
                .bucketId(BUCKET_ID)
                .entityId("entityId")
                .retrieve(new RetrievalCallback<UserData>() {
                    @Override
                    public void retrievedResults(List<NoSQLEntity<UserData>> noSQLEntities) {
                        //异步
                        assertTrue(!noSQLEntities.isEmpty());
                        UserData firstBean = noSQLEntities.get(0).getData(); // always check length of a list first...
                        assertEquals(data, firstBean);
                    }

                });


    }

    public void testDel() throws InterruptedException{

        finishCount = 0;
        NoSQLEntity<UserData> entity = new NoSQLEntity<>(BUCKET_ID, "entityId");
        final UserData data = new UserData();
        data.setName("Colin");
        data.setHeight(1.01f);
        data.setAge(12);
        entity.setData(data);
        noSQL.using(UserData.class).save(entity);
        noSQL.using(UserData.class).save(new NoSQLEntity<>(BUCKET_ID, "entity2", data));
//       To delete a single entity
        noSQL.using(UserData.class)
                .bucketId(BUCKET_ID)
                .entityId("entityId").addObserver(new OperationObserver() {
            @Override
            public void hasFinished() {
                finishCount++;

                noSQL.using(UserData.class)
                        .bucketId(BUCKET_ID)
                        .entityId("entityId")
                        .retrieve(new RetrievalCallback<UserData>() {
                            @Override
                            public void retrievedResults(List<NoSQLEntity<UserData>> noSQLEntities) {
                                assertTrue(noSQLEntities.isEmpty());
                                finishCount++;

                            }
                        });
            }
        }).delete();
        waitForThread(2);

        noSQL.using(UserData.class)
                .bucketId(BUCKET_ID)
                .retrieve(new RetrievalCallback<UserData>() {
                    @Override
                    public void retrievedResults(List<NoSQLEntity<UserData>> noSQLEntities) {
                        assertFalse(noSQLEntities.isEmpty());
                        finishCount++;
                    }
                });
        waitForThread(3);

        //      delete an entire bucket
        noSQL.using(UserData.class)
                .bucketId(BUCKET_ID).addObserver(new OperationObserver() {
            @Override
            public void hasFinished() {
                finishCount++;
            }
        }).delete();
        waitForThread(4);

        noSQL.using(UserData.class)
                .bucketId(BUCKET_ID)
                .retrieve(new RetrievalCallback<UserData>() {
                    @Override
                    public void retrievedResults(List<NoSQLEntity<UserData>> noSQLEntities) {
                        assertTrue(noSQLEntities.isEmpty());
                        finishCount++;
                    }
                });
        waitForThread(5);
    }


    private void waitForThread(int count) throws InterruptedException {
        while ( finishCount<count ) {
//            Log.d(TAG, "count:" + count);
            Thread.sleep(100);
        }
    }


    public void testList() throws Exception {
        finishCount = 0;

        final DbDataUtil dbDataUtil = new DbDataUtil();
        TimeUtils.start();
        List<NoSQLEntity<UserData>> list= new ArrayList<>();
        for (UserData userData : dbDataUtil.list) {
            list.add(new NoSQLEntity<>(BUCKET_ID,userData.getName(),userData));
        }
        noSQL.using(UserData.class).addObserver(new OperationObserver() {
            @Override
            public void hasFinished() {
                finishCount++;
                TimeUtils.end(TAG + " put list ");
                noSQL.using(UserData.class).bucketId(BUCKET_ID).retrieve(new RetrievalCallback<UserData>() {
                    @Override
                    public void retrievedResults(List<NoSQLEntity<UserData>> noSQLEntities) {
                        assertEquals(dbDataUtil.list.size(), noSQLEntities.size());
                        assertEquals(dbDataUtil.list.get(0), noSQLEntities.get(0).getData());
                        TimeUtils.end(TAG + " read list ");
                        finishCount++;
                    }
                });

            }
        }).save(list);
        waitForThread(2);
        finishCount = 0;
        TimeUtils.start();
        //query
        noSQL.using(UserData.class)
                .bucketId(BUCKET_ID)
                .filter(new DataFilter<UserData>() {
                    public boolean isIncluded(NoSQLEntity<UserData> item) {
                        if (item != null && item.getData() != null) {
                            UserData bean = item.getData();
                            return bean.getHeight()>1.5;
                        }
                        return false;
                    }
                })
                .orderBy(new DataComparator<UserData>() {
                    public int compare(NoSQLEntity<UserData> lhs, NoSQLEntity<UserData> rhs) {
                        if (lhs != null && lhs.getData() != null) {
                            if (rhs != null && rhs.getData() != null) {
                                return lhs.getData().getName().compareTo(rhs.getData().getName());
                            } else {
                                return 1;
                            }
                        } else if (rhs != null && rhs.getData() != null) {
                            return -1;
                        } else {
                            return 0;
                        }
                    }
                })
                .retrieve(new RetrievalCallback<UserData>() {
                    @Override
                    public void retrievedResults(List<NoSQLEntity<UserData>> noSQLEntities) {
                        finishCount++;
                        TimeUtils.end(TAG + " read list DataFilter");
//                        assertNotNull(noSQLEntities);
//                        assertTrue(noSQLEntities.size()>0);
                        Log.d(TAG, "noSQLEntities.size():" + noSQLEntities.size());

//                        UserData firstBean = noSQLEntities.get(0).getData(); // always check length of a list first...

                    }

                });
        waitForThread(1);


    }
}





